
#include "task_uart.h"

#include "board.h"
#include "display.h"
#include "lcd_display.h"
#include <driver/gpio.h>
#include <driver/uart.h>
#include <esp_log.h>
#include <esp_lvgl_port.h>
#include <freertos/FreeRTOS.h>
#include <freertos/queue.h>
#include <freertos/task.h>
#include <string.h>

#include "esp_heap_caps.h"

#include "application.h"
#include "assets/lang_config.h"

#define TAG "task_uart"

#define UART_PORT     UART_NUM_2
#define UART_TXD      GPIO_NUM_11
#define UART_RXD      GPIO_NUM_12
#define UART_BUF_SIZE 1024

/* ************************************************************************* */
/* ************************************************************************* */
/* ************************************************************************* */

uint8_t tm1652_data_buffer[7] = {0x08, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF};

static QueueHandle_t uart_queue;

static lv_obj_t *uart_text_label = nullptr; // 全局或静态变量

lv_obj_t *g_uart_status_label;

void create_uart_text_label() {
  if (!uart_text_label) {
    lv_obj_t *scr   = lv_scr_act();
    uart_text_label = lv_label_create(scr);
    lv_label_set_long_mode(uart_text_label, LV_LABEL_LONG_WRAP);
    lv_obj_set_width(uart_text_label, lv_pct(80));
    lv_obj_align(uart_text_label, LV_ALIGN_CENTER, 0, 0); // 居中
  }
}

static void uart_dataUpdateToDisplay(void *user_data) {
  char *received_text = (char *)user_data; // 将 user_data 强制转换回 char*

  //   if (g_uart_display_label == nullptr) {
  //     ESP_LOGE(UART_DISPLAY_TAG, "LVGL 显示标签 (g_uart_display_label) 为空，无法更新文本。");
  //     if (received_text) {
  //       free(received_text); // 即使标签为空，也要释放内存
  //     }
  //     return;
  //   }

  //   if (received_text) {
  //     lv_label_set_text(g_uart_display_label, received_text);
  //     ESP_LOGI(UART_DISPLAY_TAG, "中央标签已更新为：'%s'", received_text);
  //     free(received_text); // **关键：释放动态分配的内存**
  //   } else {
  //     ESP_LOGW(UART_DISPLAY_TAG, "接收到空文本用于 LVGL 标签更新。");
  //   }
}

static void uart_lcddisplayTest(void) {
  // 7. 创建你的用户界面
  // 获取当前活动的屏幕。在 lvgl_port_add_disp 之后，第一个添加的显示器会自动设置一个默认屏幕并激活。
  lv_obj_t *scr = lv_scr_act(); // 或者 lv_disp_get_scr_act(display_handle); 效果相同

  // ESP_LOGI(TAG, "Current screen: %p", scr);

  // 设置屏幕背景颜色（推荐，确保屏幕有可见的背景）
  //   lv_obj_set_style_bg_color(scr, lv_color_hex(0xFFFFFF), 0); // 0xFFFFFF 白色
  //   lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, 0);

  if (g_uart_status_label != NULL) {
    ESP_LOGI(TAG, "g_uart_status_label is not NULL");

    // 确保背景可见

    // lv_obj_set_style_text_color(g_uart_status_label, lv_color_hex(0x000000), 0); // 黑色字体
    // lv_obj_set_style_bg_color(scr, lv_color_hex(0xFFFFFF), 0);                   // 白色背景
    // lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, 0);

    lv_label_set_text(g_uart_status_label, "welcome to");
    // lv_obj_set_style_text_color(g_uart_status_label, lv_color_black(), 0); // 确保文本在白色背景上是黑色

  } else {
    ESP_LOGI(TAG, "g_uart_status_label is NULL");
    g_uart_status_label = lv_label_create(scr);
    lv_label_set_text(g_uart_status_label, "welcome to");

    // lv_obj_set_style_text_color(g_uart_status_label, lv_color_hex(0x000000), 0); // 黑色字体
    // lv_obj_set_style_bg_color(scr, lv_color_hex(0xFFFFFF), 0);                   // 白色背景
    // lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, 0);
  }

  // 确保不隐藏
  // lv_obj_clear_flag(g_uart_status_label, LV_OBJ_FLAG_HIDDEN);

  // lv_refr_now(NULL);

  // ESP_LOGI(TAG, "Flags: 0x%x", lv_obj_get_state(g_uart_status_label));

  // ESP_LOGI(TAG, "Label created");
}

/* ************************************************************************* */
/* ************************************************************************* */
/* ************************************************************************* */

static void uart_event_task(void *pvParameters) {
  uart_event_t event;
  uint8_t     *data = (uint8_t *)malloc(UART_BUF_SIZE);
  if (!data) {
    ESP_LOGE(TAG, "Failed to allocate receive buffer");
    vTaskDelete(NULL);
  }

  while (1) {
    if (xQueueReceive(uart_queue, &event, portMAX_DELAY)) {
      memset(data, 0, UART_BUF_SIZE);

      switch (event.type) {
      case UART_DATA: {
        int len = uart_read_bytes(UART_PORT, data, event.size, portMAX_DELAY);
        if (len > 0) {
          uart_write_bytes(UART_PORT, (const char *)data, len);
          ESP_LOGI(TAG, "Echo %d bytes: %.*s", len, len, data);

#if 0 // LVGL显示测试
      // --- 核心部分：在锁内调用 LVGL 函数 ---
      // 获取 LVGL 访问锁。这将等待 LVGL 任务释放其锁。
          if (lvgl_port_lock(0)) { // 0ms 超时意味着它会无限期地阻塞，直到获取到锁
            uart_lcddisplayTest(); // 调用你的 LVGL UI 更新函数
            lvgl_port_unlock();    // 释放 LVGL 锁
          } else {
            ESP_LOGE(TAG, "LVGL lock timeout! Cannot update UI.");
          }
#endif

          ESP_LOGI(TAG, "Total PSRAM: %d bytes", heap_caps_get_total_size(MALLOC_CAP_SPIRAM));
          ESP_LOGI(TAG, "Free PSRAM: %d bytes", heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
#if 1 // 测试播放声音
          auto &app = Application::GetInstance();
          app.PlaySound(Lang::Sounds::P3_WELCOME);
#endif
        }
        break;
      }
      case UART_FIFO_OVF:
      case UART_BUFFER_FULL:
        ESP_LOGW(TAG, "UART buffer overflow or full");
        uart_flush_input(UART_PORT);
        xQueueReset(uart_queue);
        break;

      case UART_PARITY_ERR:
        ESP_LOGE(TAG, "UART parity error");
        break;

      case UART_FRAME_ERR:
        ESP_LOGE(TAG, "UART frame error");
        break;

      default:
        ESP_LOGW(TAG, "Unknown UART event type: %d", event.type);
        break;
      }
    }
  }

  free(data);
  vTaskDelete(NULL);
}

void task_uart_init(void) {
  uart_config_t config = {
      .baud_rate  = 19200,
      .data_bits  = UART_DATA_8_BITS,
      .parity     = UART_PARITY_ODD,
      .stop_bits  = UART_STOP_BITS_1,
      .flow_ctrl  = UART_HW_FLOWCTRL_DISABLE,
      .source_clk = UART_SCLK_APB,
  };

  ESP_ERROR_CHECK(uart_param_config(UART_PORT, &config));
  ESP_ERROR_CHECK(uart_set_pin(UART_PORT, UART_TXD, UART_RXD, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
  ESP_ERROR_CHECK(uart_driver_install(UART_PORT, UART_BUF_SIZE * 2, 0, 0, NULL, 0));

  // xTaskCreate(uart_event_task, "uart_event_task", 8192, NULL, 10, NULL);
}

// 发送一帧（单字节）
static void tm1652_write(uint8_t data) {
  uart_write_bytes(UART_PORT, (const char *)&data, 1);
  // 一帧后需要有 >3ms 的空闲，表示结束
  vTaskDelay(pdMS_TO_TICKS(3));
}

void tm1652_multi_write(uint8_t *data, uint8_t len) {
  uart_write_bytes(UART_PORT, (const char *)data, len);
  // 一帧后需要有 >3ms 的空闲，表示结束
  vTaskDelay(pdMS_TO_TICKS(3));
}



// 设置显示控制（开/关 + 占空比 duty=1~15 + 段电流 current=2~8）
// 注意：current=1/8 电流太小，手册不推荐，所以默认最小=2
void tm1652_set_display(bool on, uint8_t duty, uint8_t current) {
  if (!on) {
    // 关屏命令：0x80
    tm1652_write(0x80);
    return;
  }

  if (duty > 15)
    duty = 15; // duty 范围 1~15 (1/16 ~ 15/16)
  if (duty < 1)
    duty = 1;

  if (current > 8)
    current = 8; // 段电流范围 2~8
  if (current < 2)
    current = 2;

  // 发送控制命令
  tm1652_write(0x18);

  // 生成控制调节命令字节：
  // B7~B4 = 1000 固定
  // B3~B0 = duty (1~15)
  // B2~B0 = current (1~8)
  // B0 = 显示模式 (0=8段5位, 1=7段6位)，这里默认 7段6位 (1)
  uint8_t cmd = 0x80                      // 固定高 4 位 1000
                | (duty & 0x0F) << 4      // 占空比
                | ((current - 1) & 0x07); // 电流 (1~8)

  cmd &= ~0x01; // 强制 B0=0 → 8段5位模式

  tm1652_write(cmd);
}



void tm1652_update(void) { tm1652_multi_write(tm1652_data_buffer, sizeof(tm1652_data_buffer)); }

void tm1652_set_led(uint8_t index, bool on) {
    if (index < 1 || index > 8) return;  // 编号 1~8

    uint8_t mask = 1 << (index - 1);     // SG1 → bit0, SG8 → bit7

    if (on) {
        tm1652_data_buffer[3] |= mask;   // GR3 对应的 SGx = 1 → 点亮
    } else {
        tm1652_data_buffer[3] &= ~mask;  // 清零 → 熄灭
    }

    tm1652_update();  // 发送到芯片
}



